home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 40
/
Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso
/
Aminet
/
comm
/
tcp
/
Amster.lha
/
Amster_Install
/
Source
/
share.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-07-20
|
31KB
|
1,201 lines
/*
** Amster - File sharing
** by Jacob Laursen <laursen@myself.com>
*/
#include "include/config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/mui.h"
#include <MUI/NListview_mcc.h>
#include <proto/asl.h>
#include <proto/dos.h>
#include <libraries/asl.h>
#include <libraries/dos.h>
#include <exec/memory.h>
#include <dos/exall.h>
#include <utility/tagitem.h>
#include <workbench/workbench.h>
#include "md5.h"
#include "include/protos.h"
#include "include/gui.h"
#include "include/info.h"
#include "include/share.h"
#include "include/prefs.h"
#include "include/panel.h"
#include "include/napster.h"
#include "include/upload.h"
#include "include/rexx.h"
#include "amster_Cat.h"
unsigned int numsongs=0, numbytes=0;
BOOL sharechanged=FALSE, sharefailed=FALSE;
struct FileRequester *FReqAddFiles;
struct FileRequester *FReqAddDir;
struct FileRequester *FReqLibrary;
MUIF share_dispatch(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
{
struct shdata *data;
switch(msg->MethodID) {
case OM_NEW:
return(share_new(cl, obj, (APTR)msg));
case OM_DISPOSE:
if (FReqAddFiles) FreeAslRequest(FReqAddFiles);
if (FReqAddDir) FreeAslRequest(FReqAddDir);
if (FReqLibrary) FreeAslRequest(FReqLibrary);
break;
case SHARE_OPEN:
data = INST_DATA(cl, obj);
update_stat(data);
set(obj, MUIA_Window_Open, TRUE);
return NULL;
case SHARE_CLOSE:
set(obj, MUIA_Window_Open, FALSE);
return NULL;
case SHARE_ADD:
data = INST_DATA(cl, obj);
add_shares(data);
return NULL;
case SHARE_ADDDIR:
data = INST_DATA(cl, obj);
add_directory(data);
return NULL;
case SHARE_REMOVE:
data = INST_DATA(cl, obj);
remove_shares(data, (long)(((muimsg)msg)->arg1));
return NULL;
case SHARE_SAVE:
data = INST_DATA(cl, obj);
save_shares(data);
return NULL;
case SHARE_SAVEAS:
data = INST_DATA(cl, obj);
save_shares_as(data);
return NULL;
case SHARE_LOAD:
data = INST_DATA(cl, obj);
load_shares(data);
return NULL;
case SHARE_LOADAS:
data = INST_DATA(cl, obj);
load_shares_as(data);
return NULL;
case SHARE_UPLOAD:
data = INST_DATA(cl, obj);
upload_file_confirm(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
return NULL;
case SHARE_NOTIFYALL:
data = INST_DATA(cl, obj);
notify_shares(data);
return NULL;
case SHARE_PLAY:
data = INST_DATA(cl, obj);
play_share(data);
return NULL;
case SHARE_ADDFILE:
data = INST_DATA(cl, obj);
add_file(data, (song)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
return NULL;
case SHARE_ADDFILEN:
data = INST_DATA(cl, obj);
add_filename(data, (char *)(((muimsg)msg)->arg1));
return NULL;
case SHARE_SETDIR:
strcpy(FReqAddFiles->fr_Drawer, (char *)(((muimsg)msg)->arg1));
strcpy(FReqAddDir->fr_Drawer, (char *)(((muimsg)msg)->arg1));
return NULL;
case SHARE_UPDCOUNT:
data = INST_DATA(cl, obj);
update_count(data, (char *)(((muimsg)msg)->arg1));
return NULL;
}
return(DoSuperMethodA(cl, obj, msg));
}
MUIF sharelistdest(REG(a2) APTR pool, REG(a1) sharedata sd)
{
char *path;
numsongs--;
numbytes -= sd->size;
if (gui_onlinestate == ONLINE) {
path = MakeWinPath(sd->title);
nap_sendbuf(NAPC_REMOVESHARE, path);
free(path);
}
free(sd);
return(0);
}
MUIF sharelistdisp(REG(a2) char **array, REG(a1) sharedata sd)
{
static char size[16], md5[33], time[20], bitrate[16], freq[16], count[16];
if (sd) {
*array++ = sd->title;
sprintf(size, "\33r%ld", sd->size);
*array++ = size;
sprintf(time, "\33r%ld:%02ld", sd->time/60, sd->time%60);
*array++ = time;
sprintf(bitrate, "\33r%ld", sd->bitrate);
*array++ = bitrate;
sprintf(freq, "\33l%ld", sd->freq);
*array++ = freq;
sprintf(count, "\33r%ld", sd->reqcount);
*array++ = count;
strcpy(md5, sd->md5);
*array = md5;
} else {
*array++ = (char *)MSG_LH_FILE;
*array++ = (char *)MSG_LH_SIZE;
*array++ = (char *)MSG_LH_TIME;
*array++ = (char *)MSG_LH_BITRATE;
*array++ = (char *)MSG_LH_FREQ;
*array++ = (char *)MSG_LH_COUNT;
*array = (char *)MSG_LH_CHECKSUM;
}
return(0);
}
MUIF sharelistcomp(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm)
{
sharedata entry1 = ncm->entry1;
sharedata entry2 = ncm->entry2;
LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
ULONG result = 0;
if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
if (col1 == 0) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = (LONG) stricmp(entry2->title, entry1->title);
else
result = (LONG) stricmp(entry1->title, entry2->title);
}
else if (col1 == 1) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = entry2->size - entry1->size;
else
result = entry1->size - entry2->size;
}
else if (col1 == 2) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = entry2->time - entry1->time;
else
result = entry1->time - entry2->time;
}
else if (col1 == 3) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = entry2->bitrate - entry1->bitrate;
else
result = entry1->bitrate - entry2->bitrate;
}
else if (col1 == 4) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = entry2->freq - entry1->freq;
else
result = entry1->freq - entry2->freq;
}
else if (col1 == 5) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = entry2->reqcount - entry1->reqcount;
else
result = entry1->reqcount - entry2->reqcount;
}
else if (col1 == 6) {
if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
result = (LONG) stricmp(entry2->md5, entry1->md5);
else
result = (LONG) stricmp(entry1->md5, entry2->md5);
}
if ((result != 0) || (col1 == col2)) return (result);
if (col2 == 0) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = (LONG) stricmp(entry2->title, entry1->title);
else
result = (LONG) stricmp(entry1->title, entry2->title);
}
else if (col2 == 1) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = entry2->size - entry1->size;
else
result = entry1->size - entry2->size;
}
else if (col2 == 2) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = entry2->time - entry1->time;
else
result = entry1->time - entry2->time;
}
else if (col2 == 3) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = entry2->bitrate - entry1->bitrate;
else
result = entry1->bitrate - entry2->bitrate;
}
else if (col2 == 4) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = entry2->freq - entry1->freq;
else
result = entry1->freq - entry2->freq;
}
else if (col2 == 5) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = entry2->reqcount - entry1->reqcount;
else
result = entry1->reqcount - entry2->reqcount;
}
else if (col2 == 6) {
if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
result = (LONG) stricmp(entry2->md5, entry1->md5);
else
result = (LONG) stricmp(entry1->md5, entry2->md5);
}
return (result);
}
MUIF ShareListAppMsgFunc(REG(a2) APTR obj, REG(a1) struct AppMessage **x)
{
struct WBArg *ap;
struct AppMessage *amsg = *x;
int i;
static char buf[256];
for (ap=amsg->am_ArgList, i=0; i<amsg->am_NumArgs; i++, ap++)
{
NameFromLock(ap->wa_Lock, buf, sizeof(buf));
AddPart(buf, ap->wa_Name, sizeof(buf));
DoMethod(gui->shwin, SHARE_ADDFILEN, buf);
}
return(0);
}
ULONG share_new(struct IClass *cl, Object *obj, struct opSet *msg)
{
static const struct Hook sharelistdispHook = { {NULL, NULL}, &sharelistdisp, NULL, NULL };
static const struct Hook sharelistcompHook = { {NULL, NULL}, &sharelistcomp, NULL, NULL };
static const struct Hook sharelistdestHook = { {NULL, NULL}, &sharelistdest, NULL, NULL };
static const struct Hook ShareListAppMsgHook = { {NULL, NULL}, &ShareListAppMsgFunc, NULL, NULL };
struct shdata *data;
Object *list, *stat, *addbut, *adddirbut, *rembut, *remallbut;
if (obj = (Object *)DoSuperNew(cl, obj,
MUIA_HelpNode, "sharing",
MUIA_Window_ID, MAKE_ID('S','H','A','R'),
MUIA_Window_Title, MSG_SHARE_TITLE,
MUIA_Window_AppWindow, TRUE,
WindowContents, VGroup,
MUIA_HelpNode, "sharing",
Child, stat = TextObject,
TextFrame,
MUIA_Background, MUII_TextBack,
MUIA_Text_PreParse, "\33c",
End,
Child, list = NListviewObject,
MUIA_NListview_NList, NListObject,
InputListFrame,
MUIA_NList_Title, TRUE,
MUIA_NList_Format, "BAR, BAR, BAR, BAR, BAR, BAR",
MUIA_NList_DisplayHook, &sharelistdispHook,
MUIA_NList_CompareHook2, &sharelistcompHook,
MUIA_NList_DestructHook, &sharelistdestHook,
MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default,
MUIA_NList_MinColSortable, 0,
MUIA_CycleChain, 1,
End,
End,
Child, HGroup,
Child, addbut = SimpleButton(MSG_SHARE_ADD_GAD ),
Child, adddirbut = SimpleButton(MSG_SHARE_ADDRECURSIVE_GAD),
Child, rembut = SimpleButton(MSG_SHARE_REMOVE_GAD ),
Child, remallbut = SimpleButton(MSG_SHARE_REMOVEALL_GAD ),
End,
End,
TAG_MORE, msg->ops_AttrList))
{
data = INST_DATA(cl,obj);
data->list = list;
data->stat = stat;
/* Default sort */
DoMethod(list, MUIM_Set, MUIA_NList_TitleMark, 0);
DoMethod(list, MUIM_NList_Sort3, 0, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
/* Window notify */
DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, gui->iconpanel, 1, PANEL_CLOSESHARE);
/* List notifies */
DoMethod(list, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, SHARE_PLAY);
DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
DoMethod(list, MUIM_Notify, MUIA_NList_SortType, MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark, MUIV_TriggerValue);
DoMethod(list, MUIM_Notify, MUIA_NList_SortType2, MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
DoMethod(list, MUIM_Notify, MUIA_AppMessage, MUIV_EveryTime, list, 3, MUIM_CallHook, &ShareListAppMsgHook, MUIV_TriggerValue);
/* Button notifies */
DoMethod(addbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADD );
DoMethod(adddirbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADDDIR );
DoMethod(rembut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 0);
DoMethod(remallbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 1);
/* Allocate file requesters */
FReqAddFiles = AllocAslRequestTags(ASL_FileRequest,
ASLFR_TitleText, MSG_SHARE_ADD_REQ,
ASLFR_InitialPattern, (ULONG)"#?.mp(2|3)",
ASLFR_InitialDrawer, (ULONG)prf->dlpath,
ASLFR_DoPatterns, TRUE,
ASLFR_DoMultiSelect, TRUE,
ASLFR_RejectIcons, TRUE,
TAG_DONE);
FReqAddDir = AllocAslRequestTags(ASL_FileRequest,
ASLFR_TitleText, MSG_SHARE_ADDDIR_REQ,
ASLFR_InitialDrawer, (ULONG)prf->dlpath,
ASLFR_DrawersOnly, TRUE,
TAG_DONE);
FReqLibrary = AllocAslRequestTags(ASL_FileRequest,
ASLFR_InitialFile, "Amster.shares",
ASLFR_InitialDrawer, "PROGDIR:",
ASLFR_RejectIcons, TRUE,
TAG_DONE);
return((ULONG)obj);
}
return(0);
}
/* Private functions */
void add_filename(struct shdata *data, char *fname)
{
sharedata sd;
struct FileInfoBlock *fib;
BPTR lock;
if (!(fib = AllocDosObject(DOS_FIB, NULL))) return;
if (sd = malloc(sizeof(_sharedata))) {
memset(sd, 0, sizeof(_sharedata));
strcpy(sd->title, fname);
if (lock = Lock(fname, ACCESS_READ)) {
if (Examine(lock, fib)) {
sd->size = fib->fib_Size;
if (NameFromLock(lock, sd->title, 255)) {
if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
else if (fib->fib_DirEntryType > 0) {
add_recursive(data, sd, lock, sd->title);
UnLock(lock);
}
}
else UnLock(lock);
}
}
}
FreeDosObject(DOS_FIB, fib);
}
void add_file(struct shdata *data, song sdl, char *fname)
{
sharedata sd;
struct FileInfoBlock *fib;
BPTR lock;
if (sd = malloc(sizeof(_sharedata))) {
memset(sd, 0, sizeof(_sharedata));
if (fib = AllocDosObject(DOS_FIB, NULL)) {
if (lock = Lock(fname, ACCESS_READ)) {
NameFromLock(lock, sd->title, 255);
UnLock(lock);
}
FreeDosObject(DOS_FIB, fib);
}
if (!sd->title) strcpy(sd->title, fname);
strncpy(sd->md5, sdl->md5, 32);
sd->size = sdl->size;
sd->bitrate = sdl->bit;
sd->freq = sdl->freq;
sd->time = sdl->time;
DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
numsongs++; numbytes += sd->size;
sharechanged = TRUE;
update_stat(data);
if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
}
return;
}
void add_shares(struct shdata *data)
{
sharedata sd;
BPTR lock;
struct FileInfoBlock *fib;
int i;
u_long win;
get(gui->shwin, MUIA_Window_Window, &win);
if (FReqAddFiles) {
if (AslRequestTags(FReqAddFiles, ASLFR_Window, win, TAG_DONE)) {
if (fib = AllocDosObject(DOS_FIB, NULL)) {
for (i=0; i<FReqAddFiles->fr_NumArgs; i++) {
if (sd = malloc(sizeof(_sharedata))) {
memset(sd, 0, sizeof(_sharedata));
strcpy(sd->title, FReqAddFiles->fr_Drawer);
AddPart(sd->title, FReqAddFiles->fr_ArgList[i].wa_Name, 255);
if (lock = Lock(sd->title, ACCESS_READ)) {
if (Examine(lock, fib)) {
sd->size = fib->fib_Size;
if (NameFromLock(lock, sd->title, 255)) {
if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
else if (fib->fib_DirEntryType > 0) {
add_recursive(data, sd, lock, sd->title);
UnLock(lock);
}
}
else UnLock(lock);
}
}
}
}
FreeDosObject(DOS_FIB, fib);
}
}
if (sharefailed) {
MUI_Request(gui->app, gui->shwin, 0L,
(char *)MSG_ERROR_TITLE,
(char *)MSG_OK_GAD,
(char *)MSG_SHARE_ADDFAILED);
sharefailed = FALSE;
}
}
}
void add_directory(struct shdata *data)
{
sharedata sd;
BPTR lock;
struct FileInfoBlock *fib;
u_long win;
get(gui->shwin, MUIA_Window_Window, &win);
if (FReqAddDir) {
if (AslRequestTags(FReqAddDir, ASLFR_Window, win, TAG_DONE)) {
if (fib = AllocDosObject(DOS_FIB, NULL)) {
if (sd = malloc(sizeof(_sharedata))) {
memset(sd, 0, sizeof(_sharedata));
strcpy(sd->title, FReqAddDir->fr_Drawer);
if (lock = Lock(sd->title, ACCESS_READ)) {
if (Examine(lock, fib)) {
sd->size = fib->fib_Size;
if (NameFromLock(lock, sd->title, 255)) {
if (fib->fib_DirEntryType > 0) {
add_recursive(data, sd, lock, sd->title);
UnLock(lock);
}
}
else UnLock(lock);
}
}
}
FreeDosObject(DOS_FIB, fib);
}
}
if (sharefailed) {
MUI_Request(gui->app, gui->shwin, 0L,
(char *)MSG_ERROR_TITLE,
(char *)MSG_OK_GAD,
(char *)MSG_SHARE_ADDFAILED);
sharefailed = FALSE;
}
}
}
void add_recursive(struct shdata *data, sharedata sd, BPTR dirlock, const char *dirname)
{
ULONG namelen;
long len;
struct ExAllControl *eac;
struct ExAllData *ead;
APTR eadata;
BOOL more;
char *name;
BPTR lock;
struct FileInfoBlock *fib;
const long buffersize = 4096;
if (dirlock) {
namelen = strlen(dirname);
eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
if (eac) {
eac->eac_LastKey = 0;
eac->eac_MatchString = 0;
eac->eac_MatchFunc = 0;
eadata = malloc(buffersize);
if (eadata) {
do {
more = ExAll(dirlock, eadata, buffersize, ED_TYPE, eac);
if (eac->eac_Entries > 0) {
ead = eadata;
do {
len = namelen + strlen(ead->ed_Name);
name = (char *)malloc(len+5);
if (name) {
strcpy(name, dirname);
if (AddPart(name, ead->ed_Name, len+5)) {
if (ead->ed_Type > 0) {
lock = Lock(name, ACCESS_READ);
if (lock) {
add_recursive(data, sd, lock, name);
UnLock(lock);
}
}
else if (ead->ed_Type < 0) {
if (sd = malloc(sizeof(_sharedata))) {
memset(sd, 0, sizeof(_sharedata));
strcpy(sd->title, name);
if (fib = AllocDosObject(DOS_FIB, NULL)) {
lock = Lock(name, ACCESS_READ);
if (lock) {
if (Examine(lock, fib)) {
sd->size = fib->fib_Size;
add_shareinfo(data, sd, lock);
}
}
FreeDosObject(DOS_FIB, fib);
}
}
}
}
free(name);
}
ead = ead->ed_Next;
} while(ead);
}
if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break;
if (eac->eac_Entries == 0) continue;
} while (more);
free(eadata);
}
FreeDosObject(DOS_EXALLCONTROL, eac);
}
}
}
void add_shareinfo(struct shdata *data, sharedata sd, BPTR lock)
{
unsigned int m_id, m_layer, m_bit, m_freq, m_mode;
APTR buffer;
BPTR fh;
int i=0, j=0, len, total, col;
long vbrbytes = 0, vbrframes = 0, vbr = 0;
BOOL header = FALSE;
int badhdr[10];
char *suffix;
sharedata sdtmp;
ULONG tmp;
md5_state_t state;
md5_byte_t digest[16];
int di;
/* MP3 information source:
http://mp3tech.free.fr/programmers/frame_header.html
*/
int mp3_bitrates[14][6] = {
/* V1L1,V1L2,V1L3,V2L1,V2L2,V2L3 */
{ 32, 32, 32, 32, 8, 8 },
{ 64, 48, 40, 48, 16, 16 },
{ 96, 56, 48, 56, 24, 24 },
{ 128, 64, 56, 64, 32, 32 },
{ 160, 80, 64, 80, 40, 40 },
{ 192, 96, 80, 96, 48, 48 },
{ 224, 112, 96, 112, 56, 56 },
{ 256, 128, 112, 128, 64, 64 },
{ 288, 160, 128, 144, 80, 80 },
{ 320, 192, 160, 160, 96, 96 },
{ 352, 224, 192, 176, 112, 112 },
{ 384, 256, 224, 192, 128, 128 },
{ 416, 320, 256, 224, 144, 144 },
{ 448, 384, 320, 256, 160, 160 }
};
/* V1 = MPEG Version 1
V2 = MPEG Version 2 and Version 2.5
L1 = Layer I
L2 = Layer II
L3 = Layer III
*/
int mp3_frequencies[3][3] = {
/* MPEG1, MPEG2, MPEG2.5 */
{ 44100, 22050, 11025 },
{ 48000, 24000, 12000 },
{ 32000, 16000, 8000 }
};
if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
sharefailed = TRUE;
UnLock(lock);
return;
}
suffix = sd->title + strlen(sd->title) - 4;
if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) {
gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
sharefailed = TRUE;
UnLock(lock);
return;
}
GetAttr(MUIA_NList_Entries, data->list, &tmp);
total = tmp;
while (i < total) {
DoMethod(data->list, MUIM_NList_GetEntry, i, &sdtmp);
if (sdtmp) if (strcmp(sd->title, sdtmp->title) == 0) {
gui_debugf((char *)MSG_SHARE_EXISTS, sd->title);
sharefailed = TRUE;
UnLock(lock);
return;
}
i++;
}
if (fh = OpenFromLock(lock)) {
if (buffer = AllocMem(300032, MEMF_ANY)) {
md5_init(&state);
len = Read(fh, buffer, 300032);
if (len > 0) {
md5_append(&state, (const md5_byte_t *)buffer, len);
md5_finish(&state, digest);
for (di = 0; di < 16; ++di)
sprintf(sd->md5+di*2, "%02x", digest[di]);
/* Only check first 128 kB for valid MP3 header */
if (len > 128*1024) len = 128*1024;
/* Check for VBR */
for (i=0; i<len; i++) {
if (*((unsigned char *)buffer+i) == 'X')
if (*((unsigned char *)buffer+i+1) == 'i')
if (*((unsigned char *)buffer+i+2) == 'n')
if (*((unsigned char *)buffer+i+3) == 'g') {
j = i + 7;
if ((*((char *)buffer+j) & 1) && ((*((char *)buffer+j) & 2) >> 1)) {
j++;
vbrframes = *((unsigned long *)buffer+j/4);
vbrbytes = *((unsigned long *)buffer+(j+4)/4);
j += 7;
}
if (vbrframes > 0 && vbrbytes > 0) vbr = ((vbrbytes / vbrframes) * 1000) / 3265;
break;
}
}
i = j;
if (stcd_i(buffer, badhdr) == 8 && i < 417) i = 417;
/* Work-around for "MpegDJ Encoder" bug */
while (!header && i<len-3) {
/* Seek until synchronization is found (%11111111.111xxxxx) */
if (*((unsigned char *)buffer+i) == 255) {
if (*((unsigned char *)buffer+i+1) >= 224) {
/* MPEG Audio version ID
00 - MPEG Version 2.5 (later extension of MPEG 2)
01 - reserved
10 - MPEG Version 2 (ISO/IEC 13818-3)
11 - MPEG Version 1 (ISO/IEC 11172-3)
*/
m_id = 3 - ((*((char *)buffer+i+1) & 24)>>3);
if (m_id == 3) m_id = 1;
/* Layer description
00 - reserved
01 - Layer III
10 - Layer II
11 - Layer I
*/
m_layer = 4 - ((*((char *)buffer+i+1) & (2+4))>>1);
m_bit = (*((char *)buffer+i+2) & (16+32+64+128))>>4;
m_freq = (*((char *)buffer+i+2) & (4+8))>>2;
/* Channel Mode
00 - Stereo
01 - Joint stereo (Stereo)
10 - Dual channel (2 mono channels)
11 - Single channel (Mono)
*/
m_mode = (*((char *)buffer+i+3) & (64+128))>>6;
col = m_layer-1;
if (m_id == 1) col=col+3;
if (m_bit>0 && m_bit<15 && m_freq < 3 && m_layer < 4 && m_id != 2) {
header = TRUE;
sd->freq = mp3_frequencies[m_freq][m_id];
if (vbr > 0) sd->bitrate = vbr;
else sd->bitrate = mp3_bitrates[m_bit-1][col];
if (m_layer == 2) { /* Sanity checks */
if ((sd->bitrate == 32 || sd->bitrate == 48 || sd->bitrate == 46 || sd->bitrate == 80) && m_mode != 3) header = FALSE;
if ((sd->bitrate == 224 || sd->bitrate == 256 || sd->bitrate == 320 || sd->bitrate == 384) && m_mode == 3) header = FALSE;
}
sd->time = (sd->size-i)/(sd->bitrate*125);
/* 'i' is the length of ID3v2 tag. ID3v1 size is always 128 bytes,
so it's not worth the overhead to check for this.
128 bytes of a 128 kbps MP3 = 0.000008 seconds! */
}
}
}
i++;
}
}
FreeMem(buffer, 300032);
}
Close(fh);
if (header) {
DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
numsongs++; numbytes += sd->size;
sharechanged = TRUE;
update_stat(data);
if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
}
else {
gui_debugf((char *)MSG_SHARE_ADDERROR, sd->title, sd->size, sd->bitrate, sd->freq);
sharefailed = TRUE;
}
}
else UnLock(lock);
}
void notify_shares(struct shdata *data)
{
sharedata sd;
u_long tmp;
int i, total;
if (gui_onlinestate < LOGGING_IN) return;
GetAttr(MUIA_NList_Entries, data->list, &tmp);
total = tmp;
if (total > 0) {
gui_stat((char *)MSG_STATUS2_NOTIFYALL);
for (i=0; i<total; i++) {
DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
if (!sd) break;
nap_notifyshare(sd);
}
}
}
void remove_shares(struct shdata *data, long t)
{
sharedata sd;
u_long tmp;
int total;
GetAttr(MUIA_NList_Entries, data->list, &tmp);
total = tmp;
if (total == 0) return;
switch(t) {
case 0: /* Remove marked */
set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_Selected);
update_stat(data);
set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_None);
break;
case 1: /* Remove all */
set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
for (;;) {
DoMethod(data->list, MUIM_NList_GetEntry, 0, &sd);
if (!sd) break;
DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_First);
}
update_stat(data);
set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
break;
}
sharechanged = TRUE;
}
void save_shares(struct shdata *data)
{
sharedata sd;
int i;
BPTR fh;
char buf[512], *tmp;
strcpy(buf, FReqLibrary->fr_Drawer);
AddPart(buf, FReqLibrary->fr_File, 511);
fh = Open(buf, MODE_NEWFILE);
if (!fh) return;
for (i=0; ; i++) {
DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
if (!sd) break;
tmp = strrep(sd->title, "\"", "*\"");
sprintf(buf, "\"%s\" %s %ld %ld %ld %ld REQCOUNT %ld\n", tmp, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time, sd->reqcount);
free(tmp);
Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
}
Close(fh);
sharechanged = FALSE;
}
void save_shares_as(struct shdata *data)
{
u_long win;
get(gui->win, MUIA_Window_Window, &win);
if (FReqLibrary) {
if (AslRequestTags(FReqLibrary,
ASLFR_Window, win,
ASLFR_TitleText, MSG_SHARE_SAVEAS,
ASLFR_DoSaveMode, TRUE,
TAG_DONE)) {
save_shares(data);
}
}
}
void load_shares(struct shdata *data)
{
sharedata sd;
int line = 0;
BPTR fh;
char buf[512], sharefile[512];
LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
UBYTE *argstr = "PATH/A,MD5/A,SIZE/A/N,BITRATE/A/N,FREQUENCY/A/N,TIME/A/N,REQCOUNT/K/N";
struct RDArgs *rdargs;
remove_shares(data, 1);
strcpy(sharefile, FReqLibrary->fr_Drawer);
AddPart(sharefile, FReqLibrary->fr_File, 511);
if (fh = Open(sharefile, MODE_OLDFILE)) {
set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
while (FGets(fh, buf, 512)) {
line++;
if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
rdargs->RDA_Buffer = NULL;
rdargs->RDA_Source.CS_Buffer = buf;
rdargs->RDA_Source.CS_Length = strlen(buf);
if (ReadArgs(argstr, argarray, rdargs)) {
sd = malloc(sizeof(_sharedata));
strcpy(sd->title, (char *)argarray[ ARG_PATH ]);
strcpy(sd->md5, (char *)argarray[ ARG_MD5 ]);
sd->size = *((long *)argarray[ ARG_SIZE ]);
sd->bitrate = *((long *)argarray[ ARG_BITRATE ]);
sd->freq = *((long *)argarray[ ARG_FREQ ]);
sd->time = *((long *)argarray[ ARG_TIME ]);
if (argarray[ARG_REQCOUNT]) sd->reqcount = *((long *)argarray[ ARG_REQCOUNT ]);
else sd->reqcount = 0;
DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Bottom);
numsongs++; numbytes += sd->size;
if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
FreeArgs(rdargs);
}
else gui_debugf((char *)MSG_PARSE_ERROR, sharefile, line);
FreeDosObject(DOS_RDARGS, rdargs);
}
}
set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
update_stat(data);
Close(fh);
}
sharechanged = FALSE;
}
void load_shares_as(struct shdata *data)
{
u_long win;
get(gui->win, MUIA_Window_Window, &win);
if (FReqLibrary) {
if (AslRequestTags(FReqLibrary,
ASLFR_Window, win,
ASLFR_TitleText, MSG_SHARE_LOADAS,
TAG_DONE)) {
load_shares(data);
}
}
}
void update_stat(struct shdata *data)
{
static char buf[100], totalsize[8];
char descriptor[16];
unsigned long number, tempnumber;
if (numbytes >= (1024*1024*1024)) {
strcpy(descriptor, MSG_SHARE_STAT_GB);
tempnumber = numbytes/1024/1024*10/1024;
number = tempnumber/10;
tempnumber = tempnumber-(number*10);
sprintf(totalsize,"%d.%d", number, tempnumber);
}
else if (numbytes >= (1024*1024)) {
strcpy(descriptor, MSG_SHARE_STAT_MB);
tempnumber = numbytes/1024*10/1024;
number = tempnumber/10;
tempnumber = tempnumber-(number*10);
sprintf(totalsize, "%d.%d", number, tempnumber);
}
else {
strcpy(descriptor, MSG_SHARE_STAT_KB);
number = numbytes/1024;
sprintf(totalsize, "%d", number);
}
sprintf(buf, MSG_SHARE_STAT_TMP, numsongs, totalsize, descriptor);
set(data->stat, MUIA_Text_Contents, buf);
}
void play_share(struct shdata *data)
{
sharedata sd;
char buf[1024], *command;
DoMethod(data->list, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &sd);
if (sd) {
if (prf->scripts[PRFE_PLAYMP3]) {
sprintf(buf, "Run <>NIL: %s", prf->scripts[PRFE_PLAYMP3]);
command = strrep(buf, "%f", sd->title);
Execute(command, 0, 0);
free(command);
}
}
}
void upload_req(char *user, char *fname)
{
DoMethod(gui->shwin, SHARE_UPLOAD, user, fname);
}
void upload_file_confirm(struct shdata *data, char *user, char *fname)
/* Continued from upload_req() */
{
sharedata sd;
song s;
int i=0, total;
ULONG tmp;
BOOL found = FALSE;
char *path;
GetAttr(MUIA_NList_Entries, data->list, &tmp);
total = tmp;
gui_debugf((char *)MSG_SHARE_REQFILE, user, fname);
while (i<total && !found) {
DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
if (sd) {
path = MakeWinPath(sd->title);
if (strcmp(path, fname) == 0) found = TRUE;
free(path);
}
i++;
}
if (!found) {
gui_debug((char *)MSG_SHARE_NOTFOUND);
return;
}
s = malloc(sizeof(_song));
if (!s) return;
memset(s, 0, sizeof(_song));
s->title = strdup(sd->title);
s->md5 = strdup(sd->md5);
s->size = sd->size;
s->bit = sd->bitrate;
s->freq = sd->freq;
s->time = sd->time;
s->user = strdup(user);
/* At this point we don't know IP and link speed - can't complete the struct */
ul_addq(s);
}
void update_count(struct shdata *data, char *fname)
{
sharedata sd;
int i;
long pos;
for (i=0; ; i++) {
DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
if (!sd) return;
if (strcmp(sd->title, fname) == 0) break;
}
/* Update statistics (count) */
sd->reqcount++;
sharechanged = TRUE;
pos = MUIV_NList_GetPos_Start;
DoMethod(data->list, MUIM_NList_GetPos, sd, &pos);
DoMethod(data->list, MUIM_NList_Redraw, pos);
}
void nap_notifyshare(sharedata sd)
{
char *path, *suffix;
/* In case invalid files were added manually or with an earlier version */
if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
return;
}
suffix = sd->title + strlen(sd->title) - 4;
if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) {
gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
return;
}
path = MakeWinPath(sd->title);
sprintf(nap_buf, "\"%s\" %s %ld %ld %ld %ld", path, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time);
free(path);
nap_send(NAPC_NOTIFYSHARE);
}
char *strrep(char *str1, char *old_str, char *new_str)
{
char *str;
int len, i;
if (!(str = malloc(1024))) return str1;
str[0] = '\0';
for (i=0; i<strlen(str1); i++) {
if (strncmp(str1+i, old_str, strlen(old_str)) == 0) {
strcat(str, new_str);
i += strlen(old_str)-1;
}
else {
len = strlen(str);
str[len] = str1[i];
str[len+1] = '\0';
}
}
return str;
}
char *MakeWinPath(char *AmigaPath)
/* PRE: The AmigaPath must contain max. 1 colon */
{
char *WinPath;
int i, j;
if (!(WinPath = malloc(strlen(AmigaPath)+2))) return AmigaPath;
for (i=0, j=0; i<strlen(AmigaPath); i++, j++) {
if (AmigaPath[i] == '/') WinPath[j] = '\\';
else if (AmigaPath[i] == ':') {
WinPath[j++] = ':';
WinPath[j] = '\\';
}
else WinPath[j] = AmigaPath[i];
}
WinPath[j] = '\0';
return WinPath;
}
BOOL IsIn(char *string, char c)
{
int i;
for (i=0; i<strlen(string); i++)
if (string[i] == c) return TRUE;
return FALSE;
}